home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / Mail / RCS / fio.c,v < prev    next >
Encoding:
Text File  |  1990-05-02  |  9.5 KB  |  480 lines

  1. head     1.2;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    shirriff:1.2; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.2
  10. date     90.02.08.17.51.17;  author jhh;  state Exp;
  11. branches ;
  12. next     1.1;
  13.  
  14. 1.1
  15. date     90.02.08.15.39.07;  author jhh;  state Exp;
  16. branches ;
  17. next     ;
  18.  
  19.  
  20. desc
  21. @@
  22.  
  23.  
  24. 1.2
  25. log
  26. @Ported to sprite (patched in changes from old version of mail
  27. @
  28. text
  29. @/*
  30.  * Copyright (c) 1980 Regents of the University of California.
  31.  * All rights reserved.
  32.  *
  33.  * Redistribution and use in source and binary forms are permitted
  34.  * provided that the above copyright notice and this paragraph are
  35.  * duplicated in all such forms and that any documentation,
  36.  * advertising materials, and other materials related to such
  37.  * distribution and use acknowledge that the software was developed
  38.  * by the University of California, Berkeley.  The name of the
  39.  * University may not be used to endorse or promote products derived
  40.  * from this software without specific prior written permission.
  41.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  42.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  43.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  44.  */
  45.  
  46. #ifndef lint
  47. static char sccsid[] = "@@(#)fio.c    5.20 (Berkeley) 1/16/89";
  48. #endif /* not lint */
  49.  
  50. #include "rcv.h"
  51. #include <sys/stat.h>
  52. #include <sys/file.h>
  53. #include <sys/wait.h>
  54. #include <errno.h>
  55.  
  56. /*
  57.  * Mail -- a mail program
  58.  *
  59.  * File I/O.
  60.  */
  61.  
  62. /*
  63.  * Set up the input pointers while copying the mail file into
  64.  * /tmp.
  65.  */
  66. setptr(ibuf)
  67.     register FILE *ibuf;
  68. {
  69.     register c;
  70.     register char *cp, *cp2;
  71.     register count;
  72.     char linebuf[LINESIZE];
  73.     int maybe, inhead;
  74.     FILE *mestmp;
  75.     off_t offset;
  76.     struct message this;
  77.     extern char tempSet[];
  78.  
  79.     if ((c = opentemp(tempSet)) < 0)
  80.         exit(1);
  81.     if ((mestmp = fdopen(c, "r+")) == NULL)
  82.         panic("Can't open temporary");
  83.     msgCount = 0;
  84.     maybe = 1;
  85.     inhead = 0;
  86.     offset = 0;
  87.     this.m_flag = MUSED|MNEW;
  88.     this.m_size = 0;
  89.     this.m_lines = 0;
  90.     this.m_block = 0;
  91.     this.m_offset = 0;
  92.     for (;;) {
  93.         if (fgets(linebuf, LINESIZE, ibuf) == NULL) {
  94.             if (append(&this, mestmp)) {
  95.                 perror(tempSet);
  96.                 exit(1);
  97.             }
  98. #ifdef notdef
  99.             /*
  100.              * Don't close ibuf here, because our caller
  101.              * closes it unconditionally.
  102.              */
  103.             fclose(ibuf);
  104. #endif
  105.             makemessage(mestmp);
  106.             return;
  107.         }
  108.         count = strlen(linebuf);
  109.         (void) fwrite(linebuf, sizeof *linebuf, count, otf);
  110.         if (ferror(otf)) {
  111.             perror("/tmp");
  112.             exit(1);
  113.         }
  114.         linebuf[count - 1] = 0;
  115.         if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
  116.             msgCount++;
  117.             if (append(&this, mestmp)) {
  118.                 perror(tempSet);
  119.                 exit(1);
  120.             }
  121.             this.m_flag = MUSED|MNEW;
  122.             this.m_size = 0;
  123.             this.m_lines = 0;
  124.             this.m_block = blockof(offset);
  125.             this.m_offset = offsetof(offset);
  126.             inhead = 1;
  127.         } else if (linebuf[0] == 0) {
  128.             inhead = 0;
  129.         } else if (inhead) {
  130.             for (cp = linebuf, cp2 = "status";; cp++) {
  131.                 if ((c = *cp2++) == 0) {
  132.                     while (isspace(*cp++))
  133.                         ;
  134.                     if (cp[-1] != ':')
  135.                         break;
  136.                     while (c = *cp++)
  137.                         if (c == 'R')
  138.                             this.m_flag |= MREAD;
  139.                         else if (c == 'O')
  140.                             this.m_flag &= ~MNEW;
  141.                     inhead = 0;
  142.                     break;
  143.                 }
  144.                 if (*cp != c && *cp != toupper(c))
  145.                     break;
  146.             }
  147.         }
  148.         offset += count;
  149.         this.m_size += count;
  150.         this.m_lines++;
  151.         maybe = linebuf[0] == 0;
  152.     }
  153. }
  154.  
  155. /*
  156.  * Drop the passed line onto the passed output buffer.
  157.  * If a write error occurs, return -1, else the count of
  158.  * characters written, including the newline.
  159.  */
  160. putline(obuf, linebuf)
  161.     FILE *obuf;
  162.     char *linebuf;
  163. {
  164.     register int c;
  165.  
  166.     c = strlen(linebuf);
  167.     (void) fwrite(linebuf, sizeof *linebuf, c, obuf);
  168.     (void) putc('\n', obuf);
  169.     if (ferror(obuf))
  170.         return (-1);
  171.     return (c + 1);
  172. }
  173.  
  174. /*
  175.  * Read up a line from the specified input into the line
  176.  * buffer.  Return the number of characters read.  Do not
  177.  * include the newline at the end.
  178.  */
  179. readline(ibuf, linebuf, linesize)
  180.     FILE *ibuf;
  181.     char *linebuf;
  182. {
  183.     register int n;
  184.  
  185.     clearerr(ibuf);
  186.     if (fgets(linebuf, linesize, ibuf) == NULL)
  187.         return -1;
  188.     n = strlen(linebuf);
  189.     if (n > 0 && linebuf[n - 1] == '\n')
  190.         linebuf[--n] = '\0';
  191.     return n;
  192. }
  193.  
  194. /*
  195.  * Return a file buffer all ready to read up the
  196.  * passed message pointer.
  197.  */
  198. FILE *
  199. setinput(mp)
  200.     register struct message *mp;
  201. {
  202.  
  203.     fflush(otf);
  204.     if (fseek(itf, positionof(mp->m_block, mp->m_offset), 0) < 0) {
  205.         perror("fseek");
  206.         panic("temporary file seek");
  207.     }
  208.     return (itf);
  209. }
  210.  
  211. /*
  212.  * Take the data out of the passed ghost file and toss it into
  213.  * a dynamically allocated message structure.
  214.  */
  215. makemessage(f)
  216.     FILE *f;
  217. {
  218.     register size = (msgCount + 1) * sizeof (struct message);
  219.     off_t lseek();
  220.  
  221.     if (message != 0)
  222.         free((char *) message);
  223.     if ((message = (struct message *) malloc((unsigned) size)) == 0)
  224.         panic("Insufficient memory for %d messages", msgCount);
  225.     dot = message;
  226.     size -= sizeof (struct message);
  227.     fflush(f);
  228.     (void) lseek(fileno(f), (long) sizeof *message, 0);
  229.     if (read(fileno(f), (char *) message, size) != size)
  230.         panic("Message temporary file corrupted");
  231.     message[msgCount].m_size = 0;
  232.     message[msgCount].m_lines = 0;
  233.     fclose(f);
  234. }
  235.  
  236. /*
  237.  * Append the passed message descriptor onto the temp file.
  238.  * If the write fails, return 1, else 0
  239.  */
  240. append(mp, f)
  241.     struct message *mp;
  242.     FILE *f;
  243. {
  244.     return fwrite((char *) mp, sizeof *mp, 1, f) != 1;
  245. }
  246.  
  247. /*
  248.  * Delete a file, but only if the file is a plain file.
  249.  */
  250. remove(name)
  251.     char name[];
  252. {
  253.     struct stat statb;
  254.     extern int errno;
  255.  
  256.     if (stat(name, &statb) < 0)
  257.         return(-1);
  258.     if ((statb.st_mode & S_IFMT) != S_IFREG) {
  259.         errno = EISDIR;
  260.         return(-1);
  261.     }
  262.     return unlink(name);
  263. }
  264.  
  265. static int sigdepth;        /* depth of holdsigs() */
  266. static int omask;
  267. /*
  268.  * Hold signals SIGHUP, SIGINT, and SIGQUIT.
  269.  */
  270. holdsigs()
  271. {
  272.  
  273.     if (sigdepth++ == 0)
  274.         omask = sigblock(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT));
  275. }
  276.  
  277. /*
  278.  * Release signals SIGHUP, SIGINT, and SIGQUIT.
  279.  */
  280. relsesigs()
  281. {
  282.  
  283.     if (--sigdepth == 0)
  284.         sigsetmask(omask);
  285. }
  286.  
  287. /*
  288.  * Open a temp file by creating and unlinking.
  289.  * Return the open file descriptor.
  290.  */
  291. opentemp(file)
  292.     char file[];
  293. {
  294.     int f;
  295.  
  296.     if ((f = open(file, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0)
  297.         perror(file);
  298.     remove(file);
  299.     return (f);
  300. }
  301.  
  302. /*
  303.  * Determine the size of the file possessed by
  304.  * the passed buffer.
  305.  */
  306. off_t
  307. fsize(iob)
  308.     FILE *iob;
  309. {
  310.     struct stat sbuf;
  311.  
  312.     if (fstat(fileno(iob), &sbuf) < 0)
  313.         return 0;
  314.     return sbuf.st_size;
  315. }
  316.  
  317. /*
  318.  * Evaluate the string given as a new mailbox name.
  319.  * Supported meta characters:
  320.  *    %    for my system mail box
  321.  *    %user    for user's system mail box
  322.  *    #    for previous file
  323.  *    &    invoker's mbox file
  324.  *    +file    file in folder directory
  325.  *    any shell meta character
  326.  * Return the file name as a dynamic string.
  327.  */
  328. char *
  329. expand(name)
  330.     register char *name;
  331. {
  332.     char xname[PATHSIZE];
  333.     char cmdbuf[PATHSIZE];        /* also used for file names */
  334.     register int pid, l;
  335.     register char *cp, *shell;
  336.     int pivec[2];
  337.     struct stat sbuf;
  338.     extern union wait wait_status;
  339.  
  340.     /*
  341.      * The order of evaluation is "%" and "#" expand into constants.
  342.      * "&" can expand into "+".  "+" can expand into shell meta characters.
  343.      * Shell meta characters expand into constants.
  344.      * This way, we make no recursive expansion.
  345.      */
  346.     switch (*name) {
  347.     case '%':
  348.         findmail(name[1] ? name + 1 : myname, xname);
  349.         return savestr(xname);
  350.     case '#':
  351.         if (name[1] != 0)
  352.             break;
  353.         if (prevfile[0] == 0) {
  354.             printf("No previous file\n");
  355.             return NOSTR;
  356.         }
  357.         return savestr(prevfile);
  358.     case '&':
  359.         if (name[1] == 0 && (name = value("MBOX")) == NOSTR)
  360.             name = "~/mbox";
  361.         /* fall through */
  362.     }
  363.     if (name[0] == '+' && getfold(cmdbuf) >= 0) {
  364.         sprintf(xname, "%s/%s", cmdbuf, name + 1);
  365.         name = savestr(xname);
  366.     }
  367.     /* catch the most common shell meta character */
  368.     if (name[0] == '~' && (name[1] == '/' || name[1] == '\0')) {
  369.         sprintf(xname, "%s%s", homedir, name + 1);
  370.         name = savestr(xname);
  371.     }
  372.     if (!anyof(name, "~{[*?$`'\"\\"))
  373.         return name;
  374.     if (pipe(pivec) < 0) {
  375.         perror("pipe");
  376.         return name;
  377.     }
  378.     sprintf(cmdbuf, "echo %s", name);
  379.     if ((shell = value("SHELL")) == NOSTR)
  380.         shell = SHELL;
  381.     pid = start_command(shell, 0, -1, pivec[1], "-c", cmdbuf, NOSTR);
  382.     if (pid < 0) {
  383.         close(pivec[0]);
  384.         close(pivec[1]);
  385.         return NOSTR;
  386.     }
  387.     close(pivec[1]);
  388.     l = read(pivec[0], xname, BUFSIZ);
  389.     close(pivec[0]);
  390.     if (wait_child(pid) < 0 && wait_status.w_termsig != SIGPIPE) {
  391.         fprintf(stderr, "\"%s\": Expansion failed.\n", name);
  392.         return NOSTR;
  393.     }
  394.     if (l < 0) {
  395.         perror("read");
  396.         return NOSTR;
  397.     }
  398.     if (l == 0) {
  399.         fprintf(stderr, "\"%s\": No match.\n", name);
  400.         return NOSTR;
  401.     }
  402.     if (l == BUFSIZ) {
  403.         fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name);
  404.         return NOSTR;
  405.     }
  406.     xname[l] = 0;
  407.     for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
  408.         ;
  409.     cp[1] = '\0';
  410.     if (index(xname, ' ') && stat(xname, &sbuf) < 0) {
  411.         fprintf(stderr, "\"%s\": Ambiguous.\n", name);
  412.         return NOSTR;
  413.     }
  414.     return savestr(xname);
  415. }
  416.  
  417. /*
  418.  * Determine the current folder directory name.
  419.  */
  420. getfold(name)
  421.     char *name;
  422. {
  423.     char *folder;
  424.  
  425.     if ((folder = value("folder")) == NOSTR)
  426.         return (-1);
  427.     if (*folder == '/')
  428.         strcpy(name, folder);
  429.     else
  430.         sprintf(name, "%s/%s", homedir, folder);
  431.     return (0);
  432. }
  433.  
  434. /*
  435.  * Return the name of the dead.letter file.
  436.  */
  437. char *
  438. getdeadletter()
  439. {
  440.     register char *cp;
  441.  
  442.     if ((cp = value("DEAD")) == NOSTR || (cp = expand(cp)) == NOSTR)
  443.         cp = expand("~/dead.letter");
  444.     else if (*cp != '/') {
  445.         char buf[PATHSIZE];
  446.  
  447.         (void) sprintf(buf, "~/%s", cp);
  448.         cp = expand(buf);
  449.     }
  450.     return cp;
  451. }
  452.  
  453. /*
  454.  * A nicer version of Fdopen, which allows us to fclose
  455.  * without losing the open file.
  456.  */
  457. FILE *
  458. Fdopen(fildes, mode)
  459.     char *mode;
  460. {
  461.     int f;
  462.  
  463.     if ((f = dup(fildes)) < 0) {
  464.         perror("dup");
  465.         return (NULL);
  466.     }
  467.     return fdopen(f, mode);
  468. }
  469. @
  470.  
  471.  
  472. 1.1
  473. log
  474. @Initial revision
  475. @
  476. text
  477. @d70 5
  478. d76 1
  479. @
  480.